home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 13 - 1997 (partial) / 13.01 Jan 97 / Oddone.PreemptiveThreads Folder / TrafficLight.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-03  |  25.7 KB  |  1,053 lines  |  [TEXT/CWIE]

  1. #include <Traps.h>
  2.  
  3. /* This program uses the sprintf() function to convert floating point
  4. ** numbers to strings.
  5. ** Use your favorite ANSI library (ANSI or MSL) adding the appropriate
  6. ** libraries to the project.
  7. */
  8.  
  9. #include <stdio.h>
  10. //#include <String.h>
  11.  
  12. #ifndef __FSPCOMPAT__
  13. #include    <FSpCompat.h>
  14. #endif
  15.  
  16.  
  17. #include    "Logger.h"
  18. #include    "TrapAvailable.h"
  19.  
  20. #define double2pstr(d,s)    StrLength(s) = sprintf((char *)&s[1], "%g", (double)(d))
  21. #define    CHARFROMMESSAGE(mess)    (*(((unsigned char *)(&(mess))) + 3))
  22. #define ISAPPWINDOW(w)    (((WindowPeek) w)->windowKind >= userKind)
  23. #define ISDAWINDOW(w)    (((WindowPeek) w)->windowKind < 0)
  24.  
  25. #define    kNumber_Of_Runs    70000
  26.  
  27. /* By changing the following flags you can obtain four different applications,
  28. ** the ones that were used to obtain the information published in the article.
  29. ** _PREEMPTIVERUN == 0
  30. **   _COOPYIELD   == 0  --> cooperative thread that does not yield
  31. **   _COOPYIELD   == 1  --> cooperative thread that yields the processor
  32. ** _PREEMPTIVERUN == 1
  33. **   _TESTBALANCE == 0  --> preemptive thread
  34. **   _TESTBALANCE == 1  --> preemptive thread with busy wait
  35. */
  36.  
  37. // BEGIN configuration
  38. #define    _PREEMPTIVERUN    0
  39. #define    _TESTBALANCE    0
  40. #define    _COOPYIELD    1
  41. // END configuration
  42.  
  43.  
  44. // BEGIN enforce correct dependencies
  45. #if _PREEMPTIVERUN
  46. #undef    _COOPYIELD
  47. #define    _COOPYIELD    0
  48.  
  49. #if _TESTBALANCE
  50. #define HEADERSTR    "\pPreemptive execution\rmaximum cooperative load\r"
  51. #else
  52. #define HEADERSTR    "\pPreemptive execution\r(normal)\r"
  53. #endif
  54.  
  55. #else
  56. #undef    _TESTBALANCE
  57. #define    _TESTBALANCE    0
  58.  
  59. #if _COOPYIELD
  60. #define HEADERSTR    "\pCooperative execution\r(normal)\r"
  61. #else
  62. #define HEADERSTR    "\pCooperative execution\r(not yielding)\r"
  63. #endif
  64.  
  65. #endif
  66. // END enforce correct dependencies
  67.  
  68.  
  69. #include "TrafficLight.h"        /* bring in all the #defines for Sample */
  70.  
  71.  
  72. struct OurWindowInfoRec {
  73.     ThreadID        threadID;
  74.     Boolean            stopped;
  75.     Boolean            timeToClose;
  76.     };
  77.  
  78. typedef struct OurWindowInfoRec OurWindowInfoRec;
  79. typedef OurWindowInfoRec *OurWindowInfoRecPtr;
  80.  
  81.  
  82. static Rect        gStopRect;            /* set up by Initialize */
  83. static Rect        gGoRect;            /* set up by Initialize */
  84.  
  85. /* Dhrystone stuff */
  86. double_t    gDhrystones_Per_Second;
  87. Rec_Pointer    Ptr_Glob, Next_Ptr_Glob;
  88. CursHandle    gWatchHandle;
  89. DialogPtr    gDhrystoneDialog;
  90. IOParam    *gIOParam;
  91. ThreadID    gDhrystoneThreadID;
  92. UInt32        gUser_Time = 0UL;
  93.  
  94. int            Int_Glob;
  95. int            Arr_1_Glob [50];
  96. int            Arr_2_Glob [50] [50];
  97. int            DhrystoneCount = 0;
  98.  
  99. char        Ch_1_Glob, Ch_2_Glob;
  100. Boolean        gDhrystoneDone = false;
  101. Boolean        gInBackground = false;        /* maintained by Initialize and DoEvent */
  102. Boolean        gQuit = false;
  103. Boolean        gThreads = false;
  104. Boolean        Bool_Glob;
  105.  
  106.  
  107. static void Proc_1(Rec_Pointer Ptr_Val_Par);
  108. static void Proc_2(One_Fifty *Int_Par_Ref);
  109. static void Proc_3(Rec_Pointer *Ptr_Ref_Par);
  110. static void Proc_4(void);
  111. static void Proc_5(void);
  112. static void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par);
  113. static void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref);
  114. static void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val);
  115. static Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
  116. static Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
  117. static Boolean Func_3(Enumeration Enum_Par_Val);
  118. static pascal void * DhrystoneThread(void *threadParam);
  119. static void Dhrystone(void);
  120.  
  121.  
  122. static void EventLoop( void );
  123. static void DoEvent( EventRecord *event );
  124. static void DoUpdate( WindowPtr window );
  125. static void DoActivate( WindowPtr window, Boolean becomingActive );
  126. static void DoContentClick( WindowPtr window );
  127. static void DrawWindow( WindowPtr window );
  128. static void AdjustMenus( void );
  129. static void DoMenuCommand( long menuResult );
  130. static void SetLight( WindowPtr window, Boolean newStopped );
  131. static void DoCloseWindow( WindowPtr window );
  132. static void DoNewWindow(void);
  133. static pascal void * WindowThread(void *myWindow);
  134. static void Terminate( void );
  135. static void Initialize( void );
  136. static void GestaltCheck(void);
  137. static Boolean GoGetRect( short rectID, Rect *theRect );
  138. static void ForceEnvirons( void );
  139. static void AlertUser( void );
  140. static void AlertUserContinue(short error);
  141.  
  142.  
  143. //extern void _DataInit();
  144.  
  145.  
  146. void main(void)
  147. {
  148. MaxApplZone();                    /* expand the heap so code segments load at the top */
  149.  
  150. Initialize();                    /* initialize the program */
  151. UnloadSeg(Initialize);
  152.  
  153. EventLoop();                    /* call the main event loop */
  154. }
  155.  
  156.  
  157. void EventLoop(void)
  158. {
  159. EventRecord    event;
  160.  
  161. do {    
  162.     if ( WaitNextEvent(everyEvent, &event, 0UL, nil) ) {
  163.         DoEvent(&event);
  164. #if _TESTBALANCE
  165. /* busy wait for preemptive thread */
  166.         while (gDhrystoneDone == false) ;
  167. #endif
  168.         }
  169.     else {
  170.         (void) YieldToThread(gDhrystoneThreadID);
  171.         if (gDhrystoneDone)
  172.             {
  173.             Str255 run;
  174.             Str255 result;
  175.             GrafPtr savePort;
  176.             Handle item;
  177.             Rect rect;
  178.             short typ;
  179.  
  180.             NumToString(gUser_Time, run);
  181.             run[StrLength(run) + 1] = '\t';
  182.  
  183.             double2pstr(gDhrystones_Per_Second, result);
  184.  
  185.             result[StrLength(result) + 1] = '\r';
  186.             if (gIOParam) {
  187.                 WriteToLogFile(gIOParam, &run[1], StrLength(run) + 1);
  188.                 WriteToLogFile(gIOParam, &result[1], StrLength(result) + 1);
  189.                 }
  190.  
  191.             ++DhrystoneCount;
  192.             NumToString(DhrystoneCount, run);
  193.             ParamText(run, result, nil, nil);
  194.  
  195. /* first time only */
  196.             if (DhrystoneCount == 1) {
  197.                 GetIndString(run, kDhrystoneString, 1);
  198.                 GetDialogItem(gDhrystoneDialog, kMessageItem, &typ, &item, &rect);
  199.                 SetDialogItemText(item, run);
  200.                 }
  201. /* feedback, display timings */
  202.             GetPort(&savePort);
  203.             SetPort(gDhrystoneDialog);
  204.             InvalRect(&rect);
  205.             SetPort(savePort);
  206. /* restart thread */
  207.             gDhrystoneDone = false;
  208.             (void) SetThreadState(gDhrystoneThreadID, kReadyThreadState, kNoThreadID);
  209.             }
  210.         }
  211.     }
  212. while ( gQuit == false );
  213. } /*EventLoop*/
  214.  
  215.  
  216.  
  217. void DoEvent(EventRecord    *event)
  218. {
  219. Point        aPoint = { kDILeft, kDITop };
  220. DialogPtr    dummydialogptr;
  221. WindowPtr    window;
  222. short        part, dummyitem;
  223.  
  224. if ( event->what != keyDown && event->what != autoKey && IsDialogEvent(event) )
  225.     (void)DialogSelect(event, &dummydialogptr, &dummyitem);
  226. else
  227.     switch ( event->what ) {
  228.         case mouseDown:
  229.             part = FindWindow(event->where, &window);
  230.             switch ( part ) {
  231.                 case inMenuBar:                /* process a mouse menu command (if any) */
  232.                     AdjustMenus();
  233.                     DoMenuCommand(MenuSelect(event->where));
  234.                     break;
  235.                 case inSysWindow:            /* let the system handle the mouseDown */
  236.                     SystemClick(event, window);
  237.                     break;
  238.                 case inContent:
  239.                     if ( window != FrontWindow() ) {
  240.                         SelectWindow(window);
  241.                         /*DoEvent(event);*/    /* use this line for "do first click" */
  242.                     } else
  243.                         DoContentClick(window);
  244.                     break;
  245.                 case inDrag:                /* pass screenBits.bounds to get all gDevices */
  246.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  247.                     break;
  248.                 case inGrow:
  249.                     break;
  250.                 case inGoAway:
  251.                     DoCloseWindow(window);
  252.                     break;
  253.                 case inZoomIn:
  254.                 case inZoomOut:
  255.                     if ( TrackBox(window, event->where, part) ) {
  256.                         SetPort(window);                /* the window must be the current port... */
  257.                         EraseRect(&window->portRect);    /* because of a bug in ZoomWindow */
  258.                         ZoomWindow(window, part, true);    /* note that we invalidate and erase... */
  259.                         InvalRect(&window->portRect);    /* to make things look better on-screen */
  260.                     }
  261.                     break;
  262.             }
  263.             break;
  264.         case keyDown:
  265.         case autoKey:                        /* check for menukey equivalents */
  266.             if ( event->modifiers & cmdKey )            /* Command key down */
  267.                 if ( event->what == keyDown ) {
  268.                     AdjustMenus();                        /* enable/disable/check menu items properly */
  269.                     DoMenuCommand(MenuKey(CHARFROMMESSAGE(event->message)));
  270.                     }
  271.             break;
  272.         case activateEvt:
  273.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  274.             break;
  275.         case updateEvt:
  276.             DoUpdate((WindowPtr) event->message);
  277.             break;
  278.         case diskEvt:
  279.             if ( HiWord(event->message) ) {
  280.                 DILoad();
  281.                 (void) DIBadMount(aPoint, event->message);
  282.                 DIUnload();
  283.                 }
  284.             break;
  285.         case osEvt:
  286.             if ((*(Byte *)&event->message) == suspendResumeMessage) {        /* high byte of message */
  287.                 gInBackground = (CHARFROMMESSAGE(event->message) & resumeFlag) == 0;
  288.                 DoActivate(FrontWindow(), !gInBackground);
  289.                 }
  290.             break;
  291.     }
  292. } /*DoEvent*/
  293.  
  294.  
  295. void DoUpdate(WindowPtr window)
  296. {
  297. if ( ISAPPWINDOW(window) ) {
  298.     BeginUpdate(window);                /* this sets up the visRgn */
  299.     if ( ! EmptyRgn(window->visRgn) )    /* draw if updating needs to be done */
  300.         DrawWindow(window);
  301.     EndUpdate(window);
  302.     }
  303. } /*DoUpdate*/
  304.  
  305.  
  306.  
  307. void DoActivate(WindowPtr window, Boolean becomingActive)
  308. {
  309. if ( ISAPPWINDOW(window) ) {
  310.     if ( becomingActive )
  311.         /* do whatever you need to at activation */ ;
  312.     else
  313.         /* do whatever you need to at deactivation */ ;
  314.     }
  315. } /*DoActivate*/
  316.  
  317.  
  318.  
  319. void DoContentClick(WindowPtr window)
  320. {
  321. SetLight(window, ! ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped);
  322. } /*DoContentClick*/
  323.  
  324.  
  325.  
  326. void DrawWindow(WindowPtr window)
  327. {
  328. SetPort(window);
  329.  
  330. EraseRect(&window->portRect);    /* clear out any garbage that may linger */
  331. /* draw a red (or white) stop light */
  332. ForeColor( ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped ? redColor : whiteColor);
  333. PaintOval(&gStopRect);
  334. ForeColor(blackColor);
  335. FrameOval(&gStopRect);
  336. /* draw a green (or white) go light */
  337. ForeColor( ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped ? whiteColor : greenColor);
  338. PaintOval(&gGoRect);
  339. ForeColor(blackColor);
  340. FrameOval(&gGoRect);
  341. } /*DrawWindow*/
  342.  
  343.  
  344.  
  345. void AdjustMenus(void)
  346. {
  347. WindowPtr    window;
  348. MenuHandle    menu;
  349.  
  350. window = FrontWindow();
  351.  
  352. menu = GetMenuHandle(mFile);
  353. EnableItem(menu, iNew);
  354. if (window)
  355.     EnableItem(menu, iClose);
  356.  
  357. menu = GetMenuHandle(mEdit);
  358. if (window)
  359.     if ( ISDAWINDOW(window) ) {        /* a desk accessory might need the edit menu… */
  360.         EnableItem(menu, iUndo);
  361.         EnableItem(menu, iCut);
  362.         EnableItem(menu, iCopy);
  363.         EnableItem(menu, iClear);
  364.         EnableItem(menu, iPaste);
  365.     } else {                        /* …but we don’t use it */
  366.         DisableItem(menu, iUndo);
  367.         DisableItem(menu, iCut);
  368.         DisableItem(menu, iCopy);
  369.         DisableItem(menu, iClear);
  370.         DisableItem(menu, iPaste);
  371.         }
  372.  
  373. } /*AdjustMenus*/
  374.  
  375.  
  376.  
  377. void DoMenuCommand(long menuResult)
  378. {
  379.     Str255        daName;
  380.     short        menuID;                /* the resource ID of the selected menu */
  381.     short        menuItem;            /* the item number of the selected menu */
  382.     short        itemHit;
  383.     short        daRefNum;
  384.     Boolean        handledByDA;
  385.  
  386.     menuID = HiWord(menuResult);    /* use macros for efficiency to... */
  387.     menuItem = LoWord(menuResult);    /* get menu item number and menu number */
  388.     switch ( menuID ) {
  389.         case mApple:
  390.             switch ( menuItem ) {
  391.                 case iAbout:        /* bring up alert for About */
  392.                     itemHit = Alert(rAboutAlert, nil);
  393.                     break;
  394.                 default:            /* all non-About items in this menu are DAs */
  395.                     /* type Str255 is an array in MPW 3 */
  396.                     GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
  397.                     daRefNum = OpenDeskAcc(daName);
  398.                     break;
  399.             }
  400.             break;
  401.         case mFile:
  402.             switch ( menuItem ) {
  403.                 case iNew:
  404.                     DoNewWindow();
  405.                     break;
  406.                 case iClose:
  407.                     DoCloseWindow(FrontWindow());
  408.                     break;
  409.                 case iQuit:
  410.                     Terminate();
  411.                     break;
  412.             }
  413.             break;
  414.         case mEdit:                    /* call SystemEdit for DA editing & MultiFinder */
  415.             handledByDA = SystemEdit(menuItem - 1);    /* since we don’t do any Editing */
  416.             break;
  417.         case mLight:
  418.             switch ( menuItem ) {
  419.                 case iStop:
  420.                     SetLight(FrontWindow(), true);
  421.                     break;
  422.                 case iGo:
  423.                     SetLight(FrontWindow(), false);
  424.                     break;
  425.             }
  426.             break;
  427.     }
  428.     HiliteMenu(0);                    /* unhighlight what MenuSelect (or MenuKey) hilited */
  429. } /*DoMenuCommand*/
  430.  
  431. /* Change the setting of the light. */
  432.  
  433.  
  434. void SetLight(WindowPtr window, Boolean newStopped )
  435. {
  436. if ( newStopped != ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped ) {
  437.     ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped = newStopped;
  438.     SetPort(window);
  439.     InvalRect(&window->portRect);
  440.     }
  441. } /*SetLight*/
  442.  
  443.  
  444. void
  445. DoNewWindow(void)
  446. {
  447. WindowPtr            window;
  448. OurWindowInfoRecPtr    windowInfoPtr;
  449. ThreadID            theNewThread;
  450.     
  451. if ( windowInfoPtr = (OurWindowInfoRecPtr) NewPtrClear(sizeof(OurWindowInfoRec)))    // get refCon storage
  452.     {
  453.     windowInfoPtr->threadID = kNoThreadID;    // init the thread ID
  454.     
  455.     if (window = GetNewWindow(rWindow, nil, (WindowPtr) -1))    // get the window
  456.         {    
  457.         SetWRefCon(window, (long)windowInfoPtr);    // assign it to the window
  458.         
  459.         if (NewThread(kCooperativeThread, (ThreadEntryProcPtr)WindowThread, (void *) window, 0, (kUsePremadeThread), nil, &theNewThread))
  460.             {
  461.             DisposeWindow(window);
  462.             DisposePtr((Ptr)windowInfoPtr);
  463.             AlertUserContinue(eCommandFailed);
  464.             }
  465.         else
  466.             windowInfoPtr->threadID = theNewThread;    // assign real thread ID
  467.         }
  468.     else {
  469.         DisposePtr((Ptr)windowInfoPtr);
  470.         AlertUserContinue(eCommandFailed);
  471.         }
  472.     }
  473. else
  474.     AlertUserContinue(eCommandFailed);
  475. }
  476.  
  477. void
  478. DoCloseWindow(WindowPtr window)
  479. {
  480. if (window)
  481.     if ( ISDAWINDOW(window) )
  482.         CloseDeskAcc(((WindowPeek) window)->windowKind);
  483.     else if ( ISAPPWINDOW(window) )
  484.         ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->timeToClose = true;
  485. } /*DoCloseWindow*/
  486.  
  487.  
  488. pascal void *
  489. WindowThread(void *myWindow)
  490. {
  491. WindowPtr            window;
  492. unsigned long        baseTicks, currTicks;
  493. Boolean                toggle;
  494. OurWindowInfoRecPtr    windowInfoPtr;
  495.  
  496. window = (WindowPtr) myWindow;                                            // get the window
  497. windowInfoPtr = (OurWindowInfoRecPtr) (((WindowPeek) window)->refCon);    // get the data (inited by DoNewWindow)
  498.  
  499. baseTicks = TickCount();
  500. toggle = false;
  501. for (;;)
  502.     {
  503.     if (windowInfoPtr->timeToClose)
  504.         {
  505.         DisposeWindow(window);
  506.         window = nil;
  507.         (void) DisposeThread(kCurrentThreadID, 0, true);    // and the lights go out...
  508.         }
  509.         
  510.     currTicks = TickCount();
  511.     if (baseTicks + 60 <= currTicks)
  512.         {
  513.         SetLight(window, toggle);
  514.         toggle = ! toggle;
  515.         baseTicks = currTicks;
  516.         }
  517.     
  518.     (void) YieldToThread(gDhrystoneThreadID);
  519.     }
  520.  
  521. return((void *) 'Wind');
  522. }
  523.  
  524.  
  525. void Terminate(void)
  526. {
  527. WindowPtr    aWindow;
  528. OSErr        myErr;
  529. char    ret = '\r';
  530.  
  531. while ((aWindow = FrontWindow()) != nil)
  532.     {
  533.     if (((WindowPeek) aWindow)->windowKind == dialogKind)
  534.         CloseDialog((DialogPtr) aWindow);
  535.     else
  536.         {
  537.         DoCloseWindow(aWindow);
  538.         myErr = YieldToThread(((OurWindowInfoRecPtr) (((WindowPeek) aWindow)->refCon))->threadID);
  539.         if (myErr)
  540.             DebugStr ("\p Error from YieldToThread in Terminate()");
  541.         }
  542.     }
  543. if (gIOParam) {
  544.     WriteToLogFile(gIOParam, &ret, 1);
  545.     CloseLogFile(gIOParam);
  546.     }
  547. gQuit = true;
  548. } /*Terminate*/
  549.  
  550. #pragma segment Init
  551.  
  552. void Initialize(void)
  553. {
  554. Str255    s = HEADERSTR;
  555. FSSpec    fSpec;
  556. Handle        menuBar;
  557. EventRecord event;
  558. int        count;
  559. OSErr    err;
  560. Boolean    exists;
  561.  
  562. MoreMasters();
  563. MoreMasters();
  564.  
  565. InitGraf(&qd.thePort);
  566. InitFonts();
  567. InitWindows();
  568. InitMenus();
  569. TEInit();
  570. InitDialogs(nil);
  571. FlushEvents(everyEvent, 0);
  572. InitCursor();
  573.  
  574. (void)UnloadScrap();
  575. (void)TEFromScrap();
  576.  
  577. GestaltCheck(); /* check for environment */
  578.  
  579. gWatchHandle = GetCursor(watchCursor);
  580. SetCursor(*gWatchHandle);
  581.  
  582. for (count = 1; count <= 3; count++)
  583.     EventAvail(everyEvent, &event);
  584.  
  585. (void) CreateThreadPool(kCooperativeThread, 6, 0);
  586. #if    _PREEMPTIVERUN
  587. (void) CreateThreadPool(kPreemptiveThread, 1, 0);
  588. #endif
  589.  
  590. menuBar = GetNewMBar(rMenuBar);            /* read menus into menu bar */
  591. if ( menuBar == nil )
  592.     AlertUser();
  593. SetMenuBar(menuBar);                    /* install menus */
  594. DisposeHandle(menuBar);
  595. AppendResMenu(GetMenuHandle(mApple), 'DRVR');    /* add DA names to Apple menu */
  596. DrawMenuBar();
  597.  
  598. if ( !GoGetRect(rStopRect, &gStopRect) )
  599.     AlertUser();                        /* the stop light rectangle */
  600. if ( !GoGetRect(rGoRect, &gGoRect) )
  601.     AlertUser();                        /* the go light rectangle */
  602.  
  603. gDhrystoneDialog = GetNewDialog(kDhrystoneDLOG, nil, (WindowPtr)-1);
  604.  
  605. err = FSMakeFSSpecCompat(-1, 0, "\pthreadlog", &fSpec);
  606. if (err == fnfErr)
  607.     exists = false;
  608. else if (err == noErr)
  609.     exists = true;
  610. else
  611.     AlertUser();
  612. gIOParam = OpenLogFile(&fSpec, 'CWIE', &err, exists);
  613. if (gIOParam) {
  614.     WriteToLogFile(gIOParam, &s[1], StrLength(s));
  615.     }
  616.  
  617. if (NewThread(
  618. #if    _PREEMPTIVERUN
  619. kPreemptiveThread
  620. #else
  621. kCooperativeThread
  622. #endif
  623. , (ThreadEntryProcPtr)DhrystoneThread, (void *) 0, 0, (kUsePremadeThread), nil, &gDhrystoneThreadID))
  624.     AlertUser();
  625.  
  626. InitCursor();
  627. } /*Initialize*/
  628.  
  629. /* GestaltCheck: is this Mac set up with all we need to run? */
  630.  
  631. static void GestaltCheck(void)
  632. {
  633. enum {
  634. // preemptive scheduler fix present?
  635. gestaltSchedulerFix = 3
  636. };
  637.  
  638. enum {
  639. kMinimumMemoryFree = 64L*1024
  640. };
  641.  
  642. #define    POWERMANAGER    ((1L << gestaltPMgrExists)|(1L << gestaltPMgrCPUIdle))
  643. #define TEMPMEMMANAGER    ((1L << gestaltTempMemSupport)|(1L << gestaltRealTempMemory)|(1L << gestaltTempMemTracked))
  644. long    Gresp;
  645. unsigned long    totalSize, contigSize;
  646.  
  647. PurgeSpace((long *)&totalSize, (long *)&contigSize);
  648. if (totalSize < kMinimumMemoryFree) {
  649.     AlertUser();
  650.     }
  651. if (TrapAvailable(_Gestalt)) {
  652.     if (Gestalt(gestaltThreadMgrAttr, &Gresp) == noErr) {
  653.         gThreads = (Gresp & (1L << gestaltThreadMgrPresent)) &&
  654.                     (Gresp & (1L << gestaltSchedulerFix));
  655.         }
  656.     }
  657. #if GENERATINGCFM
  658. if (gThreads)
  659.     if (NewThread == (void *)kUnresolvedCFragSymbolAddress)
  660.         gThreads = false;
  661. #endif
  662. if (gThreads == false)
  663.     AlertUser();
  664. }
  665.  
  666.  
  667. Boolean GoGetRect(short rectID, Rect *theRect)
  668. {
  669. Handle        resource;
  670.  
  671. resource = Get1Resource('RECT', rectID);
  672. return resource ? (*theRect = *(RectPtr)*resource, true) : false;
  673. } /* GoGetRect */
  674.  
  675. #pragma segment Main
  676.  
  677. /* -----------------------------------------------------------------------------
  678.  *
  679.  *                                Dhrystone.
  680.  *
  681.  * -----------------------------------------------------------------------------*/
  682.  
  683. pascal void *
  684. DhrystoneThread(void *threadParam)
  685. {
  686. #pragma unused (threadParam)
  687.  
  688. UInt32        User_Time;
  689.  
  690.  
  691. for (;;) {
  692.     User_Time = LMGetTicks();
  693.  
  694.     Dhrystone();
  695.  
  696.     User_Time = LMGetTicks() - User_Time;
  697.     gDhrystones_Per_Second = (double_t)(60 * kNumber_Of_Runs) / (double_t) User_Time;
  698.     gUser_Time = User_Time;
  699.     
  700.     (void) ThreadBeginCritical();
  701.     gDhrystoneDone = true;
  702.     (void) SetThreadStateEndCritical(kCurrentThreadID, kStoppedThreadState, kNoThreadID);
  703.     }
  704.  
  705. return((void *) 'Dhry');
  706. }
  707.  
  708. void
  709. Dhrystone(void)
  710. {
  711. One_Fifty            Int_1_Loc;
  712. register One_Fifty    Int_2_Loc;
  713. One_Fifty            Int_3_Loc;
  714. register char        Ch_Index;
  715. Enumeration            Enum_Loc;
  716. Str_30                Str_1_Loc;
  717. Str_30                Str_2_Loc;
  718. register UInt32        Run_Index;
  719. Rec_Type            fake_malloc1;
  720. Rec_Type            fake_malloc2;
  721.  
  722.  
  723. #if    _COOPYIELD
  724. UInt32        base_Time = LMGetTicks();
  725. UInt32        curr_Time;
  726. #endif
  727.  
  728. /* Initializations */
  729.  
  730. Next_Ptr_Glob = (Rec_Pointer) &fake_malloc1;
  731. Ptr_Glob = (Rec_Pointer) &fake_malloc2;
  732.  
  733. Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
  734. Ptr_Glob->Discr = Ident_1;
  735. Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
  736. Ptr_Glob->variant.var_1.Int_Comp = 40;
  737. strcpy (Ptr_Glob->variant.var_1.Str_Comp, "DHRYSTONE PROGRAM, SOME STRING");
  738. strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
  739.  
  740. /* Was missing in published program. Without this statement,    */
  741. /* Arr_2_Glob [8][7] would have an undefined value.             */
  742. /* Warning: With 16-Bit processors and kNumber_Of_Runs > 32000,  */
  743. /* overflow may occur for this array element.                   */
  744. Arr_2_Glob [8][7] = 10;
  745.  
  746. for (Run_Index = 1; Run_Index <= kNumber_Of_Runs; ++Run_Index) {
  747. //        if((Run_Index & 0xFFF) == 0) YieldToAnyThread();
  748.  
  749.     Proc_5();
  750.     Proc_4();
  751.  
  752.     /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
  753.     Int_1_Loc = 2;
  754.     Int_2_Loc = 3;
  755.     strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
  756.     Enum_Loc = Ident_2;
  757.     Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
  758.     /* Bool_Glob == 1 */
  759.     
  760.     while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
  761.         {
  762.         Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
  763.         /* Int_3_Loc == 7 */
  764.         Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
  765.         /* Int_3_Loc == 7 */
  766.         Int_1_Loc += 1;
  767.         } /* while */
  768.     
  769.     /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
  770.     Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
  771.     
  772.     /* Int_Glob == 5 */
  773.     Proc_1 (Ptr_Glob);
  774.     for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) /* loop executed twice */
  775.         {
  776.         if (Enum_Loc == Func_1 (Ch_Index, 'C')) /* then, not executed */
  777.             {
  778.             Proc_6 (Ident_1, &Enum_Loc);
  779.             strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
  780.             Int_2_Loc = Run_Index;
  781.             Int_Glob = Run_Index;
  782.             }
  783.         }
  784.     
  785.     /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
  786.     Int_2_Loc = Int_2_Loc * Int_1_Loc;
  787.     Int_1_Loc = Int_2_Loc / Int_3_Loc;
  788.     Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
  789.     
  790.     /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
  791.     Proc_2 (&Int_1_Loc);
  792.     
  793.     /* Int_1_Loc == 5 */
  794.     
  795. #if    _COOPYIELD
  796.     curr_Time = LMGetTicks();
  797.     if (curr_Time > base_Time + 10UL) {
  798.         YieldToAnyThread();
  799.         base_Time = curr_Time;
  800.         }
  801. #endif
  802.  
  803.     } /* loop "for Run_Index" */
  804. }
  805.  
  806. /* executed once */
  807. void
  808. Proc_1(/*register*/ Rec_Pointer Ptr_Val_Par)
  809. {
  810. register Rec_Pointer    Next_Record;
  811.  
  812. Next_Record = Ptr_Val_Par->Ptr_Comp; /* == Ptr_Glob_Next */
  813.  
  814. /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
  815. /* corresponds to "rename" in Ada, "with" in Pascal           */
  816.  
  817. *Ptr_Val_Par->Ptr_Comp = *Ptr_Glob; 
  818. Ptr_Val_Par->variant.var_1.Int_Comp = 5;
  819. Next_Record->variant.var_1.Int_Comp = Ptr_Val_Par->variant.var_1.Int_Comp;
  820. Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
  821. Proc_3 (&Next_Record->Ptr_Comp);
  822. /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp == Ptr_Glob->Ptr_Comp */
  823.  
  824. if (Next_Record->Discr == Ident_1) /* then, executed */
  825.     {
  826.     Next_Record->variant.var_1.Int_Comp = 6;
  827.     Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, &Next_Record->variant.var_1.Enum_Comp);
  828.     Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
  829.     Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, &Next_Record->variant.var_1.Int_Comp);
  830.     }
  831. else /* not executed */
  832.     *Ptr_Val_Par = *Ptr_Val_Par->Ptr_Comp;
  833. } /* Proc_1 */
  834.  
  835.  
  836. /* executed once */
  837. /* *Int_Par_Ref == 1, becomes 4 */
  838. void
  839. Proc_2(One_Fifty *Int_Par_Ref)
  840.     {
  841.     One_Fifty  Int_Loc;  
  842.     Enumeration   Enum_Loc;
  843.     
  844.     Int_Loc = *Int_Par_Ref + 10;
  845.     do /* executed once */
  846.     if (Ch_1_Glob == 'A') /* then, executed */
  847.         {
  848.         Int_Loc -= 1;
  849.         *Int_Par_Ref = Int_Loc - Int_Glob;
  850.         Enum_Loc = Ident_1;
  851.         } /* if */
  852.     
  853.     while (Enum_Loc != Ident_1); /* true */
  854.     } /* Proc_2 */
  855.  
  856.  
  857. /* executed once */
  858. /* Ptr_Ref_Par becomes Ptr_Glob */
  859. void
  860. Proc_3(Rec_Pointer *Ptr_Ref_Par)
  861.     {
  862.     if (Ptr_Glob != nil) /* then, executed */
  863.         *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
  864.     Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
  865.     } /* Proc_3 */
  866.  
  867.  
  868. /* executed once */
  869. void
  870. Proc_4(void)
  871.     {
  872.     Boolean Bool_Loc;
  873.     
  874.     Bool_Loc = Ch_1_Glob == 'A';
  875.     Bool_Glob = Bool_Loc | Bool_Glob;
  876.     Ch_2_Glob = 'B';
  877.     } /* Proc_4 */
  878.  
  879.  
  880. /* executed once */
  881. void
  882. Proc_5(void)
  883.     {
  884.     Ch_1_Glob = 'A';
  885.     Bool_Glob = false;
  886.     } /* Proc_5 */
  887.  
  888. /* executed once */
  889. /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
  890. void
  891. Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
  892.     {
  893.     *Enum_Ref_Par = Enum_Val_Par;
  894.     if (! Func_3 (Enum_Val_Par)) /* then, not executed */
  895.         *Enum_Ref_Par = Ident_4;
  896.     switch (Enum_Val_Par)
  897.         {
  898.         case Ident_1: 
  899.             *Enum_Ref_Par = Ident_1;
  900.             break;
  901.         case Ident_2: 
  902.             if (Int_Glob > 100)
  903.                   *Enum_Ref_Par = Ident_1;
  904.             else
  905.                 *Enum_Ref_Par = Ident_4;
  906.             break;
  907.         case Ident_3: /* executed */
  908.             *Enum_Ref_Par = Ident_2;
  909.             break;
  910.         case Ident_4: break;
  911.         case Ident_5: 
  912.             *Enum_Ref_Par = Ident_3;
  913.             break;
  914.         } /* switch */
  915.     } /* Proc_6 */
  916.  
  917.  
  918. /* executed three times                                      */ 
  919. /* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
  920. /*                  Int_Par_Ref becomes 7                    */
  921. /* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
  922. /*                  Int_Par_Ref becomes 17                   */
  923. /* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
  924. /*                  Int_Par_Ref becomes 18                   */
  925. void
  926. Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
  927.     {
  928.     One_Fifty Int_Loc;
  929.     
  930.     Int_Loc = Int_1_Par_Val + 2;
  931.     *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
  932.     } /* Proc_7 */
  933.  
  934.  
  935. /* executed once      */
  936. /* Int_Par_Val_1 == 3 */
  937. /* Int_Par_Val_2 == 7 */
  938. void
  939. Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
  940.     {
  941.     register One_Fifty Int_Index;
  942.     register One_Fifty Int_Loc;
  943.  
  944.     Int_Loc = Int_1_Par_Val + 5;
  945.     Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
  946.     Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
  947.     Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
  948.     for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
  949.         Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
  950.     Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
  951.     Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
  952.     Int_Glob = 5;
  953.     } /* Proc_8 */
  954.  
  955.  
  956. /* executed three times                                         */
  957. /* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
  958. /* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
  959. /* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
  960. Enumeration
  961. Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
  962.     {
  963.     Capital_Letter        Ch_1_Loc;
  964.     Capital_Letter        Ch_2_Loc;
  965.     
  966.     Ch_1_Loc = Ch_1_Par_Val;
  967.     Ch_2_Loc = Ch_1_Loc;
  968.     if (Ch_2_Loc != Ch_2_Par_Val) /* then, executed */
  969.         return (Ident_1);
  970.     else  /* not executed */
  971.         {
  972.         Ch_1_Glob = Ch_1_Loc;
  973.         return (Ident_2);
  974.         }
  975.     } /* Func_1 */
  976.  
  977.  
  978. /* executed once */
  979. /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
  980. /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
  981. Boolean
  982. Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
  983.     {
  984.     register One_Thirty        Int_Loc;
  985.     Capital_Letter            Ch_Loc;
  986.  
  987.     Int_Loc = 2;
  988.     while (Int_Loc <= 2) /* loop body executed once */
  989.         {
  990.         if (Func_1 (Str_1_Par_Ref[Int_Loc], Str_2_Par_Ref[Int_Loc+1]) == Ident_1) /* then, executed */
  991.             {
  992.             Ch_Loc = 'A';
  993.             Int_Loc += 1;
  994.             }
  995.         }
  996.  
  997.     if (Ch_Loc >= 'W' && Ch_Loc < 'Z') /* then, not executed */
  998.         Int_Loc = 7;
  999.  
  1000.     if (Ch_Loc == 'R') /* then, not executed */
  1001.         return (true);
  1002.     else /* executed */
  1003.         {
  1004.         if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
  1005.             /* then, not executed */
  1006.             {
  1007.             Int_Loc += 7;
  1008.             Int_Glob = Int_Loc;
  1009.             return (true);
  1010.             }
  1011.         else /* executed */
  1012.             return (false);
  1013.         } /* if Ch_Loc */
  1014. } /* Func_2 */
  1015.  
  1016.  
  1017. /* Func_3. Whether Enum_Par_Val == Ident_3 */
  1018. Boolean
  1019. Func_3 (Enumeration Enum_Par_Val)
  1020.     {
  1021.     Enumeration Enum_Loc;
  1022.  
  1023.     Enum_Loc = Enum_Par_Val;
  1024.     return (Enum_Loc == Ident_3);
  1025.     } /* Func_3 */
  1026.  
  1027. /* -----------------------------------------------------------------------------
  1028.  *
  1029.  *                                Utility routines.
  1030.  *
  1031.  * -----------------------------------------------------------------------------*/
  1032.  
  1033. void
  1034. AlertUserContinue(short /*error*/)
  1035. {
  1036. //Str255        message;
  1037.  
  1038. SetCursor(&qd.arrow);
  1039. //GetIndString(message, kErrStrings, error);
  1040. //ParamText(message, "\p", nil, nil);
  1041. (void) StopAlert(130, nil);
  1042. }
  1043.  
  1044. #pragma segment Init
  1045.  
  1046. void AlertUser(void)
  1047. {
  1048. SetCursor(&qd.arrow);
  1049. (void) StopAlert(rUserAlert, nil);
  1050. ExitToShell();
  1051. } /* AlertUser */
  1052.     
  1053.